package com.travelgroup.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.travelgroup.constant.NotificationConstant;
import com.travelgroup.domain.entity.Notification;
import com.travelgroup.domain.entity.PaymentOrder;
import com.travelgroup.domain.entity.TourGroup;
import com.travelgroup.domain.entity.User;
import com.travelgroup.enums.NotificationType;
import com.travelgroup.exception.BusinessException;
import com.travelgroup.exception.R;
import com.travelgroup.mapper.NotificationMapper;
import com.travelgroup.service.INotificationService;
import com.travelgroup.service.IUserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class NotificationServiceImpl extends ServiceImpl<NotificationMapper, Notification>
        implements INotificationService {
    @Resource
    private IUserService userService;

    /**
     * 发送信息
     * @param title
     * @param message
     * @param group
     * @param user
     * @param rememberIds
     */
    @Override
    public void sendNotification(String title, String message, TourGroup group, User user, List<Long> rememberIds) {
        // 设置消息标题及内容
        String content = String.format(message,
                user.getUsername(), group.getId(),
                group.getCurrentMembers(), group.getMaxMembers());

        List<Long> recipientIds = rememberIds.stream()
                .filter(r -> !r.equals(user.getId()))
                .toList();
        if (!recipientIds.isEmpty()) {
            batchSendNotifications(title, content, NotificationType.JOIN, recipientIds);
        }
    }

    /**
     * 发送支付信息
     * @param title
     * @param message
     * @param orderNo
     * @param groupId
     * @param userId
     */
    @Override
    public void sendPaidNotification(String title, String message, String orderNo, Long groupId, Long userId) {
        String content = String.format(message,
                orderNo, groupId);
        sendSystemNotification(userId, title, content);
    }

    /**
     * 批量发送信息
     * @param title
     * @param content
     * @param type
     * @param recipientIds
     */
    @Transactional
    public void batchSendNotifications(String title, String content, NotificationType type, List<Long> recipientIds) {
        List<Notification> notifications = new ArrayList<>();

        for (Long userId : recipientIds) {
            Notification notification = new Notification();
            notification.setTitle(title);
            notification.setContent(content);
            notification.setUserId(userId);
            notification.setType(type);
            notification.setIsRead(false);
            notifications.add(notification);
        }

        if (!this.saveBatch(notifications)) {
            throw new BusinessException("消息发送失败");
        }
    }

    /**
     * 获取我的信息
     * @return
     */
    @Override
    public R<List<Notification>> queryMyNotifications() {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Notification> notifications = this.lambdaQuery().
                eq(Notification::getUserId, userId)
                .list();
        if (notifications.isEmpty()) {
            return R.success("消息列表为空", notifications);
        }
        return R.success("获取消息列表成功", notifications);
    }

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @Override
    public R<Notification> queryNotificationById(Long id) {
        Notification notification = this.getById(id);
        if (notification == null) {
            throw new BusinessException("消息不存在");
        }
        notification.setIsRead(true);
        if (!this.updateById(notification)) {
            throw new BusinessException("消息状态更新失败");
        }
        return R.success("获取消息信息成功", notification);
    }

    /**
     * 发送退款信息
     * @param userId
     * @param title
     * @param message
     * @param orderNo
     * @param amount
     */
    @Override
    public void sendRefundNotification(Long userId, String title, String message, String orderNo, String amount) {
        String content = String.format(message,
                orderNo, amount);
        sendSystemNotification(userId, title, content);
    }

    /**
     * 发送系统信息
     * @param userId
     * @param title
     * @param content
     */
    private void sendSystemNotification(Long userId, String title, String content) {
        Notification notification = new Notification();
        notification.setTitle(title);
        notification.setContent(content);
        notification.setUserId(userId);
        notification.setIsRead(false);
        notification.setType(NotificationType.SYSTEM);
        if (!this.save(notification)) {
            throw new BusinessException("消息发送失败");
        }
    }

    /**
     * 批量发送通知
     * @param organizerId
     * @param groupTitle
     * @param paymentOrders
     * @param cancelReason
     */
    @Override
    @Transactional
    public void sendCancellationNotifications(Long organizerId, String groupTitle,
                                               List<PaymentOrder> paymentOrders,
                                               String cancelReason) {
        // 给举办者发送通知
        User organizer = userService.getById(organizerId);
        this.sendRefundNotification(organizer.getId(),
                NotificationConstant.CANCEL_INITIATE_TITLE,
                NotificationConstant.CANCEL_INITIATE_MESSAGE,
                groupTitle, cancelReason
        );

        // 给所有参与者发送通知
        for (PaymentOrder order : paymentOrders) {
            User participant = userService.getById(order.getUserId());
            sendRefundNotification(participant.getId(),
                    NotificationConstant.CANCEL_JOIN_TITLE,
                    NotificationConstant.CANCEL_JOIN_MESSAGE,
                    groupTitle,cancelReason
            );

            // 发送退款进度通知
            sendRefundNotification(
                    order.getUserId(),
                    NotificationConstant.REFUND_TITLE,
                    NotificationConstant.REFUND_MESSAGE,
                    order.getOrderNo(), order.getAmount().toString()
            );

        }
    }
}
